package com.heartbeat.spider.impl;

import java.util.Date;
import java.util.List;

import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.heartbeat.domain.Page;
import com.heartbeat.domain.Site;
import com.heartbeat.spider.PageDao;
import com.heartbeat.spider.PageService;
import com.heartbeat.spider.SiteDao;
import com.heartbeat.util.Parser;

public class PageServiceImpl implements PageService {
	private Parser parser = new Parser();
	
	private PageDao pageDao = new PageDaoImpl();
	
	private SiteDao siteDao  = new SiteDaoImpl();
	
	@Override
	public void spideChildPage(Page page) {
		// TODO Auto-generated method stub
		Site site = siteDao.getSiteById(page.getSiteId());
		boolean isSucced = this.getAllUrlInPage(page.getUrl(), site.getCodeType(), page.getDomainName(), page.getSiteId());
		if(isSucced){
			page.setHasSpided(true);
			
			pageDao.updatePage(page);
		}
		
	}

	@Override
	public void spideHomePage(Site site) {
		// TODO Auto-generated method stub
		this.getAllUrlInPage(site.getUrl(), site.getCodeType(), site.getUrl(), site.getId());

	}

	/**
	 * 抓取页面上所有符合规定的Url
	 * @param currentUrl 需解析页面的Url
	 * @param codeType 页面编码类型
	 * @param domainName 页面域名
	 * @param siteId 站点Id
	 * @return 返回是否抓取成功
	 */
	private boolean getAllUrlInPage(String currentUrl, String codeType, String domainName, int siteId){
		boolean result = false;
		
		Document doc = parser.getDocument(currentUrl, codeType);
		if(doc == null){
			return result;
		}
		NodeList nodeList = parser.getNodeList(doc, "//A");

		int nodeListLength = nodeList.getLength();
		Node node = null;
		for (int i = 0; i < nodeListLength; i++) {
			node = nodeList.item(i);
			NamedNodeMap nameNodeMap = node.getAttributes();
			Node tempNode = nameNodeMap.getNamedItem("href");
			if(tempNode == null){
				continue;
			}
			String toPatchUrl = tempNode.getNodeValue();
			String patchedUrl = this.patchUrl(domainName, currentUrl, toPatchUrl);
			//System.out.println(patchedUrl);
			Date now = new Date();
			if(patchedUrl != null){
				//根据hashcode判断该页面是否已经存储过
				int hashCode = patchedUrl.hashCode();
				Page page = pageDao.getPageByHashCode(hashCode);
				if(page == null){
					page = new Page();
					page.setCreateTime(now);
					page.setDomainName(domainName);
					page.setHashCode(hashCode);
					page.setSiteId(siteId);
					page.setUrl(patchedUrl);
					page.setHasSpided(false);
					page.setHasSpidedContent(false);
					
					pageDao.savePage(page);
				}
			}
		}
		
		if(nodeListLength>0){
			result = true;
		}
		
		return result;
	}
	
	/**
	 * 补充完整URL
	 * @param domainName 域名
	 * @param currentUrl 当前解析的页面
	 * @param toPatchUrl 需补全完整的URL
	 * @return
	 */
	private String patchUrl(String domainName, String currentUrl, String toPatchUrl){
		String patchedUrl = null;
		
		//如果链接地址为完整地址
		if(toPatchUrl.indexOf(domainName)>=0){
			patchedUrl = toPatchUrl;
			return patchedUrl;
		}
		//如果为外链
		if(toPatchUrl.indexOf(domainName)<0 && toPatchUrl.indexOf("http://")>=0){
			return patchedUrl;
		}
		
		//如果为绝对路径
		if(toPatchUrl.indexOf(domainName)<0 && toPatchUrl.indexOf("http://")<0&&"/".equals(toPatchUrl.substring(0, 1))){
			patchedUrl=domainName+toPatchUrl.substring(1);
			return patchedUrl;
		}
		
		//如果为相对路径
		if(toPatchUrl.indexOf(domainName)<0 && toPatchUrl.indexOf("http://")<0&&!"/".equals(toPatchUrl.substring(0, 1))){
			String relative = currentUrl.substring(0, currentUrl.lastIndexOf("/"));
			patchedUrl = relative + "/" + toPatchUrl;
			return patchedUrl;
		}
		
		return null;
	}
	
	public static void main(String args[]){
		/*SiteDao siteDao  = new SiteDaoImpl();
		List<Site> siteList = siteDao.getAllSiteToSpide();
		
		PageService pageService = new PageServiceImpl();
		for(Site site : siteList){
			pageService.spideHomePage(site);
		}*/
		PageDao pageDao = new PageDaoImpl();
		//Page  page = pageDao.getPageById(9);
		List<Page> pageList = pageDao.getToSpidePageBySiteId(1);
		
		//System.out.println(pageList.size());
		PageService pageService = new PageServiceImpl();
		//pageService.spideChildPage(page);
		for(Page page : pageList){
			pageService.spideChildPage(page);
		}
		
	}
}
